package com.docker.login;

import com.docker.core.constant.MainConstant;
import com.docker.sys.app.AppBean;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import kit.docker.convert.ConvertKit;
import kit.docker.exception.BaseException;
import kit.docker.redis.RedisConstant;
import kit.docker.redis.RedisKit;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class LoginRedis {

    private static String getCacheName() {
        return MainConstant.REDIS_DOCKER;
    }

    // ========================= 图形验证码 ======================================
    private static String buildCaptchaKey(String key) {
        return RedisConstant.USER_LOGIN_CAPTCHA + key;
    }

    public static void setCaptcha(String key, String value) {
        RedisKit.set(getCacheName(), buildCaptchaKey(key), value, PropKit.getInt(RedisConstant.USER_LOGIN_CAPTCHA_TIMEOUT, 180));
    }

    public static String getCaptcha(String key) {
        return RedisKit.get(getCacheName(), buildCaptchaKey(key));
    }

    public static void delCaptcha(String key) {
        RedisKit.del(getCacheName(), buildCaptchaKey(key));
    }

    // ========================= 登陆错误次数 ======================================
    private static String buildLoginErrorKey(String appId, String account) {
        return RedisConstant.USER_LOGIN_ERROR + appId + ":" + account;
    }

    public static int getLoginErrorNum(String appId, String account) {
        String loginErrorKey = buildLoginErrorKey(appId, account);
        if (RedisKit.exists(getCacheName(), loginErrorKey)) {
            return Integer.parseInt(RedisKit.get(getCacheName(), loginErrorKey));
        }
        return 0;
    }

    public static long getLoginErrorStopTime(String appId, String account) {
        String loginErrorKey = buildLoginErrorKey(appId, account);
        if (RedisKit.exists(getCacheName(), loginErrorKey)) {
            return RedisKit.ttl(getCacheName(), loginErrorKey);
        }
        return 0;
    }

    public static void addLoginErrorNum(String appId, String account) {
        int count = getLoginErrorNum(appId, account) + 1;
        if (count >= PropKit.getInt(RedisConstant.USER_LOGIN_ERROR_MAXNUM, 3)) {
            RedisKit.set(getCacheName(), buildLoginErrorKey(appId, account), String.valueOf(count), PropKit.getInt(RedisConstant.USER_LOGIN_ERROR_STOPTIME, 10) * 60);
        } else {
            RedisKit.set(getCacheName(), buildLoginErrorKey(appId, account), String.valueOf(count));
        }
    }

    public static void delLoginErrorNum(String appId, String account) {
        RedisKit.del(getCacheName(), buildLoginErrorKey(appId, account));
    }

    // ========================= 用户会话session ======================================

    public static void initUserLoginSession(AppBean app, List<Record> users) {
        for (Record user : users) {
            initUserLoginSession(app, user.getColumns());
        }
    }

    public static void initUserLoginSession(AppBean app, Map<String, Object> user) {
        String userSessionKey = RedisConstant.USER_SESSION_TOKEN + app.getApp_id() + ":" + user.get("token");
        String appSessionKey = RedisConstant.USER_SESSION_APP + user.get("user_id") + ":" + app.getApp_id();
        //默认有效期为30min
        RedisKit.hmset(getCacheName(), userSessionKey, user, (StrKit.notNull(app.getToken_expire()) ? app.getToken_expire() : 30) * 60);
        RedisKit.hmset(getCacheName(), appSessionKey, user, (StrKit.notNull(app.getToken_expire()) ? app.getToken_expire() : 30) * 60);
    }

    public static void delUserLoginSession(String appId, String token) {
        String userSessionKey = RedisConstant.USER_SESSION_TOKEN + appId + ":" + token;
        String loginUserId = RedisKit.hget(getCacheName(), userSessionKey, "user_id");
        if (StrKit.isBlank(loginUserId)) {
            throw new BaseException("退出登录失败");
        }
        delUserSession(appId, loginUserId);
        String appSessionKey = RedisConstant.USER_SESSION_APP + loginUserId + ":" + appId;
        RedisKit.del(getCacheName(), appSessionKey);
    }

    private static void delUserSession(String appId, String loginUserId) {
        String userSessionP = RedisConstant.USER_SESSION_TOKEN + appId + ":*";
        Set<String> keys = RedisKit.getKeys(getCacheName(), userSessionP);
        for (String key : keys) {
            String userId = RedisKit.hget(getCacheName(), key, "user_id");
            if (StrKit.equals(loginUserId, userId)) {
                RedisKit.del(getCacheName(), key);
            }
        }
    }

    public static void rollUserLoginSession(AppBean app, String token) {
        String appIdKey = RedisConstant.USER_SESSION_TOKEN + app.getApp_id() + ":" + token;
        String userId = RedisKit.hget(getCacheName(), appIdKey, "user_id");
        String userIdKey = RedisConstant.USER_SESSION_APP + userId + ":" + app.getApp_id();
        //默认有效期为30min
        RedisKit.expire(getCacheName(), appIdKey, (StrKit.notNull(app.getToken_expire()) ? app.getToken_expire() : 30) * 60);
        RedisKit.expire(getCacheName(), userIdKey, (StrKit.notNull(app.getToken_expire()) ? app.getToken_expire() : 30) * 60);
    }

    public static <T> T getSessionUser(String appId, String token, Class<T> clazz) {
        String key = RedisConstant.USER_SESSION_TOKEN + appId + ":" + token;
        if (!RedisKit.exists(MainConstant.REDIS_DOCKER, key)) {
            return null;
        }
        return ConvertKit.mapToObjectStr(RedisKit.hgetAll(getCacheName(), key), clazz);
    }

    public static boolean existSmsCode(String appId, String account) {
        return RedisKit.exists(getCacheName(), buildSmsCode(appId, account));
    }

    private static String buildSmsCode(String appId, String account) {
        return RedisConstant.USER_LOGIN_SMSCODE + appId + ":" + account;
    }

    public static long ttlSmsCode(String appId, String account) {
        if (existSmsCode(appId, account)) {
            return RedisKit.ttl(getCacheName(), buildSmsCode(appId, account));
        }
        return 0;
    }

    public static void initSmsCode(String appId, String account, String smsCode, Integer time) {
        RedisKit.set(getCacheName(), buildSmsCode(appId, account), smsCode, time);
    }

    public static boolean valiSmsCode(String appId, String account, String smsCode) {
        if (existSmsCode(appId, account)) {
            String nowCode = getSmsCode(appId, account);
            return nowCode.equalsIgnoreCase(smsCode);
        }
        return false;
    }

    private static String getSmsCode(String appId, String account) {
        return RedisKit.get(getCacheName(), buildSmsCode(appId, account));
    }

    public static void delSmsCode(String appId, String account) {
        RedisKit.del(getCacheName(), buildSmsCode(appId, account));
    }

}
